@file:Suppress("MemberVisibilityCanBePrivate", "EqualsOrHashCode", "unused")

package com.virtualightning.mvvm.tools.shapes

import android.view.View

/**
 *  Anchor : Create by CimZzz
 *  Time : 2021/12/14 16:57
 *  尺寸
 */
class VLSize(
	// 宽
	var width: Float = 0f,
	// 高
	var height: Float = 0f
) {
	// 高宽比
	var heightWidthRatio: Float = 0f
	// 上次比例放大宽度的增量
	var lastScaleWidthInc: Float = 0f
	// 上次比例放大高度的增量
	var lastScaleHeightInc: Float = 0f

	override fun toString(): String = "VLSize(width: $width, height: $height)"

	override fun equals(other: Any?): Boolean {
		if(other is VLSize) {
			return other.width == width && other.height == height
		}
		return super.equals(other)
	}

	init {
		heightWidthRatio = if(isValid()) {
			height / width
		} else {
			0f
		}
	}


	/**
	 * 重置尺寸
	 */
	fun reset() {
		width = 0f
		height = 0f
		lastScaleWidthInc = 0f
		lastScaleHeightInc = 0f
	}

	/**
	 * 设置尺寸
	 * @param size VLSize 其他尺寸对象
	 */
	fun set(size: VLSize) {
		width = size.width
		height = size.height
		heightWidthRatio = if(isValid()) {
			height / width
		} else {
			0f
		}
	}

	/**
	 * 设置尺寸
	 * @param width Float 高
	 * @param height Float 宽
	 */
	fun set(width: Float, height: Float) {
		this.width = width
		this.height = height
		heightWidthRatio = if(isValid()) {
			height / width
		} else {
			0f
		}
	}

	/**
	 * 是否为一个合法尺寸（宽高均大于 0）
	 * @return Boolean
	 */
	fun isValid(): Boolean {
		return width > 0f && height > 0f
	}

	/**
	 * 获取按比例缩放至指定尺寸的缩放因子
	 * @param size VLSize 其他尺寸对象
	 * @return Float 缩放因子
	 */
	fun getFitFactor(size: VLSize): Float {
		if(!isValid() || !size.isValid()) {
			return 0f
		}
		return (size.width / width).coerceAtMost(size.height / height)
	}

	/**
	 * 获取按比例填充至指定尺寸的缩放因子
	 * @param size VLSize 其他尺寸对象
	 * @return Float 缩放因子
	 */
	fun getFillFactor(size: VLSize): Float {
		if(!isValid() || !size.isValid()) {
			return 0f
		}
		return (size.width / width).coerceAtLeast(size.height / height)
	}

	/**
	 * 将尺寸比例缩放至源尺寸，结果保存在目标尺寸中
	 * @param src VLSize 源尺寸对象
	 * @param dst VLSize 目标尺寸对象
	 */
	fun fitSizeTo(src: VLSize, dst: VLSize) {
		if(!isValid() || !src.isValid()) {
			dst.reset()
			return
		}
		val factor = getFitFactor(src)
		dst.set(this)
		dst.scaleByWidth(factor)
	}

	/**
	 * 将尺寸比例填充至源尺寸，结果保存在目标尺寸中
	 * @param src VLSize 源尺寸对象
	 * @param dst VLSize 目标尺寸对象
	 */
	fun fillSizeTo(src: VLSize, dst: VLSize) {
		if(!isValid() || !src.isValid()) {
			dst.reset()
			return
		}
		val factor = getFillFactor(src)
		dst.set(this)
		dst.scaleByWidth(factor)
	}

	/**
	 * 判断是否尺寸是否一致
	 * @param width Float 高
	 * @param height Float 宽
	 * @return Boolean 如果一致返回 true
	 */
	fun same(width: Float, height: Float): Boolean {
		return this.width == width && this.height == height
	}

	/**
	 * 缩放到指定宽度
	 * @param afterWidth Float 变化后宽度
	 */
	fun scaleToWidth(afterWidth: Float) {
		if(afterWidth == 0f) {
			return
		}
		val afterHeight = afterWidth * heightWidthRatio
		lastScaleWidthInc = afterWidth - width
		lastScaleHeightInc = afterHeight - height
		width = afterWidth
		height = afterHeight
	}


	/**
	 * 缩放到指定高度
	 * @param afterHeight Float 变化后高度
	 */
	fun scaleToHeight(afterHeight: Float) {
		if(afterHeight == 0f || heightWidthRatio == 0f) {
			return
		}
		val afterWidth = afterHeight / heightWidthRatio
		lastScaleWidthInc = afterWidth - width
		lastScaleHeightInc = afterHeight - height
		width = afterWidth
		height = afterHeight
	}



	/**
	 * 根据宽度按比例放大
	 * @param factor Float 比例因子
	 */
	fun scaleByWidth(factor: Float) {
		if(factor == 0f) {
			return
		}
		val afterWidth = factor * width
		val afterHeight = afterWidth * heightWidthRatio
		lastScaleWidthInc = afterWidth - width
		lastScaleHeightInc = afterHeight - height
		width = afterWidth
		height = afterHeight
	}

	/**
	 * 根据高度按比例放大
	 * @param factor Float 比例因子
	 */
	fun scaleByHeight(factor: Float) {
		if(factor == 0f) {
			return
		}
		val afterHeight = factor * height
		val afterWidth = afterHeight / heightWidthRatio
		lastScaleWidthInc = afterWidth - width
		lastScaleHeightInc = afterHeight - height
		width = afterWidth
		height = afterHeight
	}

	/**
	 * 返回与目标尺寸宽度差值
	 * @param size VLSize 目标尺寸
	 * @return Float 宽度差值
	 */
	fun diffWidth(size: VLSize): Float {
		return width - size.width
	}

	/**
	 * 返回与目标尺寸高度差值
	 * @param size VLSize 目标尺寸
	 * @return Float 高度差值
	 */
	fun diffHeight(size: VLSize): Float {
		return height - size.height
	}

	/**
	 * 判断尺寸是否相等
	 * @param width Float 宽
	 * @param height Float 高
	 * @return Boolean 相等返回 true
	 */
	fun equals(width: Float, height: Float): Boolean {
		return this.width == width && this.height == height
	}
}

/**
 * 获取视图尺寸
 * @receiver View
 * @return VLSize 尺寸
 */
fun View.getVLSize(): VLSize {
	return VLSize(width = width.toFloat(), height = height.toFloat())
}

/**
 * 获取视图测量尺寸
 * @receiver View
 * @return VLSize 测量尺寸
 */
fun View.getMeasureVLSize(): VLSize {
	return VLSize(width = measuredWidth.toFloat(), height = measuredHeight.toFloat())
}